package D001redis.com;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public class A001_hash一致性分布均匀问题 {

    public static Map<Long, AtomicLong> map = new ConcurrentHashMap<>();

    public static void main(String[] args) {

        //一池可扩容线程
        ExecutorService threadPool = Executors.newFixedThreadPool(20);

        Long start = System.currentTimeMillis();

        int num = 1000 * 10000;
        //10个顾客请求
        try {
            for (int i = 1; i <= num; i++) {
                //执行
                threadPool.execute(() -> {
                    String str = getStringRandom(20);
//                    Long hashCode = myHashCode(str);
                    Long hashCode = Long.valueOf(str.hashCode() & Integer.MAX_VALUE);
                    Long key = hashCode % 128L;
                    AtomicLong value = map.get(key) == null ? new AtomicLong(0) : map.get(key);

//                    System.out.println("str=" + str + "\thashCode=" + hashCode + "\tkey=" + key + "\tvalue" + value);
                    value.incrementAndGet();
                    map.put(key, value);
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭
            threadPool.shutdown();
        }

        int time = 0;
        AtomicInteger atomicTime = new AtomicInteger(0);
        while (threadPool.isTerminated()==false){
            System.out.println(atomicTime.incrementAndGet() + "\tthreadPool.isTerminated():" + threadPool.isTerminated());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        Long end = System.currentTimeMillis();
        System.out.println("处理数据量:" + num + "\t耗时:" + ((end-start) / 1000) + "秒");

        for (Map.Entry<Long, AtomicLong> stringStringEntry : map.entrySet()) {
            System.out.println(stringStringEntry.getKey() + "\t\t\t" + stringStringEntry.getValue());
        }

    }


    //生成随机数字和字母,
    public static Random random = new Random();
    public static String getStringRandom(int length) {

        String val = "";

        //参数length，表示生成几位随机数
        for (int i = 0; i < length; i++) {

            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            //输出字母还是数字
            if ("char".equalsIgnoreCase(charOrNum)) {
                //输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                val += (char) (random.nextInt(26) + temp);
            } else if ("num".equalsIgnoreCase(charOrNum)) {
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val;
    }

    private static long myHashCode(String str) {
        long h = 0;
        if (h == 0) {
            int off = 0;
            char val[] = str.toCharArray();
            long len = str.length();

            for (long i = 0; i < len; i++) {
                h = 31 * h + val[off++];
            }
        }
        return h;
    }
}
